# -*- coding: utf-8 -*-
# @author: Longxing Tan, tanlongxing888@163.com
# @date: 2020-03
# This script is used for testing the new data
import math
import sys
import os

from utils.metrics import metric
from utils.wsg import WGS84ToGK_Single

os.environ["CUDA_VISIBLE_DEVICES"]="-1"
filePath = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.split(filePath)[0])

import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
import tensorflow as tf

# 需要转化的模型文件路径
# model_path = "saved_models/attention_seq2seq"
# settings = "seq2seq_[ds]ospline_big_ep200_bt128_nlstm512_2021-05-12_09-47-43"
settings1 = [
    # "lstm2lstm_dsospline_big_ep200_bt128_nlstm512_2021-05-16_17-36-42",
    "gru2gru_dsospline_big_ep200_bt128_nlstm512_2021-05-16_14-36-38",
    "seq2seq_[ds]ospline_big_ep200_bt128_nlstm512_2021-05-12_09-47-43"
]
model_list = []
for setting in settings1:
    model_path = "saved_models/seq2seq/{}".format(setting)
    model = tf.saved_model.load(model_path)
    # model.summary()
    model_list.append(model)

import pandas as pd
import numpy as np
from utils.norm_feature import FeatureNorm
from utils.prepare_feature import transform2_lagged_feature_md, multi_step_y_md, postprocess

dir_name = "ospline_big"
columns = ['date', 'mmsi', 'sog', 'lng', 'lat', 'cog', 'deltatime', 'deltalng', 'deltalat']
input_columns = ['deltatime','deltalng', 'deltalat', 'sog', 'cog']
output_columns = ['deltatime','deltalng', 'deltalat', 'sog', 'cog']
# output_columns = ['lng', 'lat']
# output_columns = ['deltatime','deltalng', 'deltalat', 'sog', 'cog']

feature_norm = FeatureNorm()
weights_dir = "weights/" + dir_name

input_seq_length = 40
output_seq_length = 20
'''
liner
[1.10000000e+04 1.17000000e-04 2.13000000e-04 1.21567045e+02
 3.13471680e+01 1.09000000e+01 3.59900000e+02]
[ 0.00000000e+00 -1.65000000e-04 -3.33000000e-04  1.21451832e+02
  3.10146170e+01  2.60000000e+00  0.00000000e+00]
'''
'''
ospline
[1.00000000e+03 8.00000000e-05 6.50000000e-05 1.21567045e+02
 3.13473130e+01 1.70821860e+01 3.59999335e+02]
[ 0.0000000e+00 -8.1000000e-05 -6.2000000e-05  1.2145183e+02
  3.1014617e+01  2.3876000e-02  4.0000000e-04]
'''
'''
ospline big
[1.00000000e+03 8.00000000e-05 7.20000000e-05 1.70821860e+01
 3.59999735e+02]
[ 0.0000e+00 -8.1000e-05 -6.2000e-05  1.7765e-02  4.0000e-04]
'''
deltatime_max = 1.00000000e+03
deltatime_min = 0.0
deltalng_max = 8.00000000e-05
deltalng_min = -8.1000000e-05
deltalat_max = 7.20000000e-05
deltalat_min = -6.2000e-05

lng_max = 1.21567045e+02
lng_min = 1.2145183e+02
lat_max = 3.13473130e+01
lat_min = 3.1014617e+01
sog_max = 1.70821860e+01
sog_min = 2.3876000e-02
cog_max = 3.59999335e+02
cog_min = 4.0000000e-04
cnt = 1

# data_file = 'datasets/liner/train/255806202_01-03-2019_08-16-36.csv'
# data_file = 'DataSet/datasets/liner/train/355079000_01-03-2019_09-06-20.csv'
# data_file = 'DataSet/datasets/liner/train/412047290_01-03-2019_13-15-09.csv'
# data_file = 'DataSet/datasets/liner/valid/412377190_01-03-2019_19-20-13.csv'
# data_file = 'DataSet/datasets/ospline/valid/412358380_01-03-2019_15-42-03.csv'
# data_file = 'DataSet/datasets/ospline_big/train/273352000_04-03-2019_13-56-13.csv'

iter = 100
# 直道1 ok no 20
# file_name = '412047560_03-03-2019_09-31-59'
# 直道2 ok no.125
# file_name = '412377040_03-03-2019_21-18-15'
# 直道3 no5
# file_name = '412550750_03-03-2019_13-45-13'

# 弯道1
# file_name = '412377040_03-03-2019_21-18-15' # ok No.52 85 125直
# 弯道2
# file_name = '412376530_03-03-2019_07-51-23' # valid No.18也许可以
# 弯道3 No.99
file_name = '412047560_03-03-2019_09-15-08' # valid

merror_csv_path = './merr/{}.csv'.format('wandao_test') # zhidao

# file_name = '413793534_01-03-2019_13-37-30'
data_file = 'DataSet/datasets/ospline_big/valid/{}.csv'.format(file_name)
# data_file = 'DataSet/datasets/ospline_big/train/{}.csv'.format(file_name)

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
def write_msg_to_file(merr):
    print(merr)
    file_name = merror_csv_path
    with open(file_name, 'a') as f:
        f.write(merr)
        f.write('\n')

def plot_pre_time(x, y, y_pred, idx=0):
    print(x.shape) # (40, 5)
    lng = x[:, 3] * (lng_max - lng_min) + lng_min
    lat = x[:, 4] * (lat_max - lat_min) + lat_min

    print(y.shape)  # (20, 5)
    delta_lng_true = y[:, 1] * (deltalng_max - deltalng_min) + deltalng_min
    delta_lat_true = y[:, 2] * (deltalat_max - deltalat_min) + deltalat_min

    print(y_pred.shape)  # (20, 5)
    delta_lng_pred = y_pred[:, 1] * (deltalng_max - deltalng_min) + deltalng_min
    delta_lat_pred = y_pred[:, 2] * (deltalat_max - deltalat_min) + deltalat_min

    # lng_pred = y_pred[:, 3] * (lng_max - lng_min) + lng_min
    # lat_pred = y_pred[:, 4] * (lat_max - lat_min) + lat_min

    # 取最后一个点
    start_lat = lat[-1];start_lon = lng[-1]
    print(start_lon, start_lat)
    pred_lon = [start_lon];pred_lat = [start_lat]
    true_lon = [start_lon];true_lat = [start_lat]
    for i in delta_lat_pred:
        pred_lat.append(pred_lat[-1] + i)
    for i in delta_lng_pred:
        pred_lon.append(pred_lon[-1] + i)

    for i in delta_lat_true:
        true_lat.append(true_lat[-1]+i)
    for i in delta_lng_true:
        true_lon.append(true_lon[-1]+i)
    loss_lat = [true_lat[i] - pred_lat[i] for i in range(len(true_lat))]
    loss_lon = [true_lon[i] - pred_lon[i] for i in range(len(true_lon))]
    # 获取误差多少米
    m_loss = get_x_y_loss(true_lon, true_lat, pred_lon, pred_lat)
    print("m_loss", m_loss)
    write_msg_to_file(','.join([str(x) for x in m_loss]))
    print("=======true_lon======")
    print(true_lon)
    plt.rcParams['figure.figsize'] = (7,6)
    plt.plot(pred_lat, pred_lon, 'b*', label='预测轨迹点')
    plt.plot(true_lat, true_lon, color="red", linestyle='', marker='o', markerfacecolor='white', label='真实轨迹点',alpha = 0.4)
    plt.xlim(min(min(pred_lat),min(true_lat)) - 0.000001, max(max(pred_lat),max(true_lat)) + 0.000001)  # 确定横轴坐标范围
    plt.ylim(min(min(pred_lon),min(true_lon)) - 0.000001,  max(max(pred_lon),max(true_lon)) + 0.000001)
    plt.xlabel('纬度', fontsize=11)
    plt.ylabel('经度', fontsize=11)
    plt.legend()
    # plt.subplot(4, 1, 2)
    # plt.plot(delta_lng_true, label='delta_lng_true')
    # plt.plot(delta_lng_pred, label='delta_lng_pred')
    # plt.legend()
    # plt.subplot(4, 1, 3)
    # plt.plot(delta_lat_true, label='delta_lat_true')
    # plt.plot(delta_lat_pred, label='delta_lat_pred')
    # plt.legend()
    # plt.subplot(4, 1, 4)
    # plt.plot(m_loss, label='误差(米)')
    # plt.legend()
    global cnt
    plt.savefig('./result/{}_{}.jpg'.format(file_name, cnt))
    cnt += 1
    plt.show()
from haversine import haversine
from geopy.distance import geodesic
def get_x_y_loss(true_lon, true_lat, pred_lon, pred_lat):
    ans = []
    point_true = zip(true_lat, true_lon)
    print("list(point_true)",list(point_true))
    point_pred = zip(pred_lat, pred_lon)

    for lon, lat, lon_p, lat_p in zip(true_lon, true_lat, pred_lon, pred_lat):
        # dis = haversine(a, b)
        x, y = WGS84ToGK_Single(lat, lon)
        x_p, y_p = WGS84ToGK_Single(lat_p, lon_p)
        # dis = geodesic((lat, lon), (lat_p, lon_p)).m
        dis = math.sqrt((x_p - x) ** 2 + (y_p - y)**2)
        ans.append(dis)
    return ans
def main(plot=True):
    temp_data = pd.read_csv(data_file, names=columns)
    temp_data = temp_data[input_columns]
    x = feature_norm(temp_data, model_dir=weights_dir, mode='val')
    y = x[output_columns]

    # 滑动窗口取x
    x = transform2_lagged_feature_md(x, window_sizes=input_seq_length, out_windows_size=output_seq_length)
    y = multi_step_y_md(y, predict_window=output_seq_length, input_window=input_seq_length)

    print("x.shape:{}  y.shape:{}".format(x.shape, y.shape))
    assert x.shape[0] == y.shape[0]
    x, y = postprocess(x, y)

    # model = Model(params=params, use_model='pb')
    # 逐个预测
    y_pred = []
    for a in tqdm(range(x.shape[0])):
        if a != iter:
            continue
        batch_x = x[a];save_x = batch_x
        batch_x=batch_x[np.newaxis,:]
        batch_y = y[a]
        batch_y=batch_y[np.newaxis,:]

        batch_x_mask = np.zeros_like(batch_y)
        y_p_list = []
        for model in model_list:
            f = model.signatures["serving_default"]
            # f = model.signatures[("input_1", "input_2")]
            y_p = f(input_1 = tf.constant(batch_x.tolist()), input_2 = tf.constant(batch_x_mask.tolist()))
            y_p = y_p['dense'].numpy()
            # y_p = y_p['output_layer'].numpy()
            y_p=np.squeeze(y_p, axis=0)
            y_p_list.append(y_p)

        batch_y=np.squeeze(batch_y, axis=0);save_y = batch_y
        plot_pre_time(save_x, save_y, y_p, idx=a)

        # plot_pre_time2(save_x, save_y, y_p_list[0], y_p_list[1])
        # plt.show()

if __name__ == '__main__':
    # dis = haversine((121.1, 31), (121.5, 31.1));
    # print(dis/1000.0)
    main(plot=True)
